package adapletplugin.editors;

import objects.Type;

import org.eclipse.jface.viewers.IStructuredContentProvider;
import org.eclipse.jface.viewers.ITableLabelProvider;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.window.Window;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.ScrolledComposite;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.forms.widgets.FormToolkit;

import adapletplugin.dialogs.NewAttributeDialog;

public class TypeEditor extends AbstractSubEditor
{
	private Text fTypeNameText;
	private Text fTableText;

	private Text fDerivesText;

	private Text fIdColText;
	private Text fTypeColText;
	private Text fTypeAliasText;
	private Text fNameColText;
	private Text fRevColText;
	private Text fPrevRevColText;
	private Text fNextRevColText;
	private Text fPolicyColText;
	private Text fStateColText;
	private Text fDescColText;
	private Text fOwnerColText;
	private Text fOrigColText;
	private Text fModColText;
	private Type typeFocus;

	// TABLE for attributes
	private Button fNewAttributeButton;
	private TableViewer fAttributeTable;

	public TypeEditor(ScrolledComposite composite, FormToolkit toolkit, MapFileEditor parentEditor)
	{
		super(composite, toolkit, parentEditor);
	}

	@Override
	protected void create()
	{
		Composite row = fToolkit.createComposite(fSubComposite);
		row.setLayout(new GridLayout(2, false));
		row.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));

		fToolkit.createLabel(row, "Type Name:");
		fTypeNameText = fToolkit.createText(row, "", SWT.BORDER | SWT.READ_ONLY);
		fTypeNameText.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
		fTypeNameText.addModifyListener(createModifyListener_TypeName());

		fToolkit.createLabel(row, "Table Name:");
		fTableText = fToolkit.createText(row, "", SWT.BORDER);
		fTableText.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
		fTableText.addModifyListener(createModifyListener_Table());

		fToolkit.createLabel(row, "Derives Type:");
		fDerivesText = fToolkit.createText(row, "", SWT.BORDER);
		fDerivesText.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
		fDerivesText.addModifyListener(createModifyListener_Derives());

		fToolkit.createLabel(row, "ID Column:");
		fIdColText = fToolkit.createText(row, "", SWT.BORDER);
		fIdColText.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
		fIdColText.addModifyListener(createModifyListener_ID());

		fToolkit.createLabel(row, "Type Column:");
		fTypeColText = fToolkit.createText(row, "", SWT.BORDER);
		fTypeColText.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
		fTypeColText.addModifyListener(createModifyListener_Type());

		fToolkit.createLabel(row, "Type Alias:");
		fTypeAliasText = fToolkit.createText(row, "", SWT.BORDER);
		fTypeAliasText.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
		fTypeAliasText.addModifyListener(createModifyListener_TypeAlias());

		fToolkit.createLabel(row, "Name Column:");
		fNameColText = fToolkit.createText(row, "", SWT.BORDER);
		fNameColText.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
		fNameColText.addModifyListener(createModifyListener_Name());

		fToolkit.createLabel(row, "Revision Column:");
		fRevColText = fToolkit.createText(row, "", SWT.BORDER);
		fRevColText.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
		fRevColText.addModifyListener(createModifyListener_Rev());

		fToolkit.createLabel(row, "Previous Revision Column:");
		fPrevRevColText = fToolkit.createText(row, "", SWT.BORDER);
		fPrevRevColText.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
		fPrevRevColText.addModifyListener(createModifyListener_Prev());

		fToolkit.createLabel(row, "Next Revision Column:");
		fNextRevColText = fToolkit.createText(row, "", SWT.BORDER);
		fNextRevColText.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
		fNextRevColText.addModifyListener(createModifyListener_Next());

		fToolkit.createLabel(row, "Policy Column:");
		fPolicyColText = fToolkit.createText(row, "", SWT.BORDER);
		fPolicyColText.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
		fPolicyColText.addModifyListener(createModifyListener_Policy());

		fToolkit.createLabel(row, "State Column:");
		fStateColText = fToolkit.createText(row, "", SWT.BORDER);
		fStateColText.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
		fStateColText.addModifyListener(createModifyListener_State());

		fToolkit.createLabel(row, "Description Column:");
		fDescColText = fToolkit.createText(row, "", SWT.BORDER);
		fDescColText.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
		fDescColText.addModifyListener(createModifyListener_Desc());

		fToolkit.createLabel(row, "Owner Column:");
		fOwnerColText = fToolkit.createText(row, "", SWT.BORDER);
		fOwnerColText.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
		fOwnerColText.addModifyListener(createModifyListener_Owner());

		fToolkit.createLabel(row, "Originated Column:");
		fOrigColText = fToolkit.createText(row, "", SWT.BORDER);
		fOrigColText.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
		fOrigColText.addModifyListener(createModifyListener_Orig());

		fToolkit.createLabel(row, "Modified Column:");
		fModColText = fToolkit.createText(row, "", SWT.BORDER);
		fModColText.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
		fModColText.addModifyListener(createModifyListener_Mod());

		fNewAttributeButton = fToolkit.createButton(fSubComposite, "Add Attribute", SWT.PUSH);
		fNewAttributeButton.setLayoutData(new GridData(SWT.RIGHT, SWT.FILL, false, false));
		fNewAttributeButton.addSelectionListener(createNewAttributeListener());

		fAttributeTable = new TableViewer(fSubComposite, SWT.BORDER | SWT.V_SCROLL | SWT.SINGLE | SWT.FULL_SELECTION);
		fAttributeTable.getTable().setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
		fAttributeTable.setContentProvider(new AttributeTableContentProvider());
		fAttributeTable.setLabelProvider(new AttributeTableLabelProvider());

		TableColumn col = new TableColumn(fAttributeTable.getTable(), SWT.LEFT);
		col.setMoveable(false);
		col.setResizable(true);
		col.setText("Attribute");
		col.setWidth(100);

		col = new TableColumn(fAttributeTable.getTable(), SWT.RIGHT);
		col.setMoveable(false);
		col.setResizable(true);
		col.setText("Table Column");
		col.setWidth(100);

		fAttributeTable.getTable().setHeaderVisible(true);

		fAttributeTable.setInput(new AttributeTableInput(typeFocus));
	}

	private SelectionListener createNewAttributeListener()
	{
		return new SelectionAdapter() {
			
			@Override
			public void widgetSelected(SelectionEvent e)
			{
				Shell shell = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell();
				
				NewAttributeDialog dialog = new NewAttributeDialog(shell);
				
				dialog.create();
				dialog.open();
				
				if(dialog.getReturnCode() == Window.OK)
				{
					typeFocus.addAttribute(dialog.getAttribute(), dialog.getColumn());
					
					fAttributeTable.refresh();
					fEditor.refresh();
				}
			}
		};
	}

	private ModifyListener createModifyListener_TypeName()
	{
		return new ModifyListener() {

			@Override
			public void modifyText(ModifyEvent e)
			{
				typeFocus.setTypeName(fTypeNameText.getText());
				// TODO update map

				fEditor.refresh();
			}
		};
	}

	private ModifyListener createModifyListener_Table()
	{
		return new ModifyListener() {

			@Override
			public void modifyText(ModifyEvent e)
			{
				typeFocus.setTableName(fTableText.getText());
				fEditor.refresh();
			}
		};
	}

	private ModifyListener createModifyListener_Derives()
	{
		return new ModifyListener() {

			@Override
			public void modifyText(ModifyEvent e)
			{
				typeFocus.setDerives(fDerivesText.getText());
				fEditor.refresh();
			}
		};
	}

	private ModifyListener createModifyListener_ID()
	{
		return new ModifyListener() {

			@Override
			public void modifyText(ModifyEvent e)
			{
				typeFocus.setID(fIdColText.getText());
				fEditor.refresh();
			}
		};
	}

	private ModifyListener createModifyListener_Type()
	{
		return new ModifyListener() {

			@Override
			public void modifyText(ModifyEvent e)
			{
				typeFocus.setType(fTypeColText.getText());
				fEditor.refresh();
			}
		};
	}

	private ModifyListener createModifyListener_TypeAlias()
	{
		return new ModifyListener() {

			@Override
			public void modifyText(ModifyEvent e)
			{
				typeFocus.setTypeAlias(fTypeAliasText.getText());
				fEditor.refresh();
			}
		};
	}

	private ModifyListener createModifyListener_Name()
	{
		return new ModifyListener() {

			@Override
			public void modifyText(ModifyEvent e)
			{
				typeFocus.setName(fNameColText.getText());
				fEditor.refresh();
			}
		};
	}

	private ModifyListener createModifyListener_Rev()
	{
		return new ModifyListener() {

			@Override
			public void modifyText(ModifyEvent e)
			{
				typeFocus.setRevision(fRevColText.getText());
				fEditor.refresh();
			}
		};
	}

	private ModifyListener createModifyListener_Prev()
	{
		return new ModifyListener() {

			@Override
			public void modifyText(ModifyEvent e)
			{
				typeFocus.setPreviousRevision(fPrevRevColText.getText());
				fEditor.refresh();
			}
		};
	}

	private ModifyListener createModifyListener_Next()
	{
		return new ModifyListener() {

			@Override
			public void modifyText(ModifyEvent e)
			{
				typeFocus.setNextRevision(fNextRevColText.getText());
				fEditor.refresh();
			}
		};
	}

	private ModifyListener createModifyListener_Policy()
	{
		return new ModifyListener() {

			@Override
			public void modifyText(ModifyEvent e)
			{
				typeFocus.setPolicy(fPolicyColText.getText());
				fEditor.refresh();
			}
		};
	}

	private ModifyListener createModifyListener_State()
	{
		return new ModifyListener() {

			@Override
			public void modifyText(ModifyEvent e)
			{
				typeFocus.setState(fStateColText.getText());
				fEditor.refresh();
			}
		};
	}

	private ModifyListener createModifyListener_Desc()
	{
		return new ModifyListener() {

			@Override
			public void modifyText(ModifyEvent e)
			{
				typeFocus.setDescription(fStateColText.getText());
				fEditor.refresh();
			}
		};
	}

	private ModifyListener createModifyListener_Owner()
	{
		return new ModifyListener() {

			@Override
			public void modifyText(ModifyEvent e)
			{
				typeFocus.setOwner(fOwnerColText.getText());
				fEditor.refresh();
			}
		};
	}

	private ModifyListener createModifyListener_Orig()
	{
		return new ModifyListener() {

			@Override
			public void modifyText(ModifyEvent e)
			{
				typeFocus.setOriginated(fOrigColText.getText());
				fEditor.refresh();
			}
		};
	}

	private ModifyListener createModifyListener_Mod()
	{
		return new ModifyListener() {

			@Override
			public void modifyText(ModifyEvent e)
			{
				typeFocus.setModified(fModColText.getText());
				fEditor.refresh();
			}
		};
	}

	@Override
	protected void updateFields()
	{
		typeFocus = (Type) fFocusObject;

		fTypeNameText.setText(typeFocus.getTypeName());
		fTableText.setText(typeFocus.getTableName());
		fDerivesText.setText(typeFocus.getDerives());
		fIdColText.setText(typeFocus.getID());
		fTypeColText.setText(typeFocus.getType());
		fTypeAliasText.setText(typeFocus.getTypeAlias());
		fNameColText.setText(typeFocus.getName());
		fRevColText.setText(typeFocus.getRevision());
		fPrevRevColText.setText(typeFocus.getPreviousRevision());
		fNextRevColText.setText(typeFocus.getNextRevision());
		fPolicyColText.setText(typeFocus.getPolicy());
		fStateColText.setText(typeFocus.getState());
		fDescColText.setText(typeFocus.getDescription());
		fOwnerColText.setText(typeFocus.getOwner());
		fOrigColText.setText(typeFocus.getOriginated());
		fModColText.setText(typeFocus.getModified());

		fAttributeTable.setInput(new AttributeTableInput(typeFocus));
	}

	private class AttributeTableContentProvider implements IStructuredContentProvider
	{

		@Override
		public void dispose()
		{

		}

		@Override
		public void inputChanged(Viewer viewer, Object oldInput, Object newInput)
		{

		}

		@Override
		public Object[] getElements(Object inputElement)
		{
			return ((AttributeTableInput) inputElement).getData();
		}

	}

	private class AttributeTableLabelProvider extends LabelProvider implements ITableLabelProvider
	{

		@Override
		public Image getColumnImage(Object element, int columnIndex)
		{
			return null;
		}

		@Override
		public String getColumnText(Object element, int columnIndex)
		{
			if (columnIndex == 0)
			{
				return (String) element;
			}
			else if (columnIndex == 1)
			{
				return typeFocus.getAttributeColumn((String) element);
			}
			else
			{
				return "INVALID COLUMN";
			}
		}

	}

	private class AttributeTableInput
	{
		private Type fInput;

		public AttributeTableInput(Type type)
		{
			fInput = type;
		}

		public String[] getData()
		{
			if (fInput == null)
			{
				return new String[0];
			}
			return fInput.getAttributeNames();
		}
	}

}
